﻿namespace TNet
{
    using System;
    using System.IO;
    using System.Net;

    public class ServerList
    {
        public List<Entry> list = new List<Entry>();

        public Entry Add(Entry newEntry, long time)
        {
            List<Entry> list = this.list;
            lock (list)
            {
                for (int i = 0; i < this.list.size; i++)
                {
                    Entry entry = this.list[i];
                    if (entry.internalAddress.Equals(newEntry.internalAddress) && entry.externalAddress.Equals(newEntry.externalAddress))
                    {
                        entry.name = newEntry.name;
                        entry.playerCount = newEntry.playerCount;
                        entry.recordTime = time;
                        return entry;
                    }
                }
                newEntry.recordTime = time;
                this.list.Add(newEntry);
            }
            return newEntry;
        }

        public Entry Add(string name, int playerCount, IPEndPoint internalAddress, IPEndPoint externalAddress, long time)
        {
            List<Entry> list = this.list;
            lock (list)
            {
                for (int i = 0; i < this.list.size; i++)
                {
                    Entry entry = this.list[i];
                    if (entry.internalAddress.Equals(internalAddress) && entry.externalAddress.Equals(externalAddress))
                    {
                        entry.name = name;
                        entry.playerCount = playerCount;
                        entry.recordTime = time;
                        this.list[i] = entry;
                        return entry;
                    }
                }
                Entry item = new Entry {
                    name = name,
                    playerCount = playerCount,
                    internalAddress = internalAddress,
                    externalAddress = externalAddress,
                    recordTime = time
                };
                this.list.Add(item);
                return item;
            }
        }

        private void AddInternal(Entry newEntry, long time)
        {
            for (int i = 0; i < this.list.size; i++)
            {
                Entry entry = this.list[i];
                if (entry.internalAddress.Equals(newEntry.internalAddress) && entry.externalAddress.Equals(newEntry.externalAddress))
                {
                    entry.name = newEntry.name;
                    entry.playerCount = newEntry.playerCount;
                    entry.recordTime = time;
                    return;
                }
            }
            newEntry.recordTime = time;
            this.list.Add(newEntry);
        }

        public bool Cleanup(long time)
        {
            time -= 0x1b58L;
            bool flag = false;
            List<Entry> list = this.list;
            lock (list)
            {
                int index = 0;
                while (index < this.list.size)
                {
                    Entry entry = this.list[index];
                    if (entry.recordTime < time)
                    {
                        flag = true;
                        this.list.RemoveAt(index);
                    }
                    else
                    {
                        index++;
                    }
                }
            }
            return flag;
        }

        public void Clear()
        {
            List<Entry> list = this.list;
            lock (list)
            {
                this.list.Clear();
            }
        }

        public void ReadFrom(BinaryReader reader, long time)
        {
            if (reader.ReadUInt16() == 1)
            {
                List<Entry> list = this.list;
                lock (list)
                {
                    int num = reader.ReadUInt16();
                    for (int i = 0; i < num; i++)
                    {
                        Entry newEntry = new Entry();
                        newEntry.ReadFrom(reader);
                        this.AddInternal(newEntry, time);
                    }
                }
            }
        }

        public bool Remove(IPEndPoint internalAddress, IPEndPoint externalAddress)
        {
            List<Entry> list = this.list;
            lock (list)
            {
                for (int i = 0; i < this.list.size; i++)
                {
                    Entry entry = this.list[i];
                    if (entry.internalAddress.Equals(internalAddress) && entry.externalAddress.Equals(externalAddress))
                    {
                        this.list.RemoveAt(i);
                        return true;
                    }
                }
            }
            return false;
        }

        public void WriteTo(BinaryWriter writer)
        {
            writer.Write((ushort) 1);
            List<Entry> list = this.list;
            lock (list)
            {
                writer.Write((ushort) this.list.size);
                for (int i = 0; i < this.list.size; i++)
                {
                    this.list[i].WriteTo(writer);
                }
            }
        }

        public class Entry
        {
            public object data;
            public IPEndPoint externalAddress;
            public IPEndPoint internalAddress;
            public string name;
            public int playerCount;
            public long recordTime;

            public void ReadFrom(BinaryReader reader)
            {
                this.name = reader.ReadString();
                this.playerCount = reader.ReadUInt16();
                Tools.Serialize(reader, out this.internalAddress);
                Tools.Serialize(reader, out this.externalAddress);
            }

            public void WriteTo(BinaryWriter writer)
            {
                writer.Write(this.name);
                writer.Write((ushort) this.playerCount);
                Tools.Serialize(writer, this.internalAddress);
                Tools.Serialize(writer, this.externalAddress);
            }
        }
    }
}

